﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace uzing
{
    public class CTcpClient
    {
        //private object writeState = null;
        //private object readState = null;

        private AsyncCallback writeCallback = null;
        private AsyncCallback readCallback = null;

        private byte[] mReadBuffer;
        private int mReadSize;
        private int mReadOffset;

        private TcpClient client;

        public CTcpClient(TcpClient nativeClient)
        {
            client = nativeClient;
        }

        public void Read(byte[] buffer, int offset, int size)
        {
            var stream = client.GetStream();
            int readSize = stream.Read(buffer, offset, size);
            if (readSize < size)
            {
                int tmpOffset = 0;
                while (readSize + tmpOffset < size)
                {
                    tmpOffset += readSize;
                    readSize = stream.Read(buffer, offset + tmpOffset, size - tmpOffset);
                }
            }
        }

        public void Write(byte[] buffer, int offset, int size)
        {
            var stream = client.GetStream();
            stream.Write(buffer, offset, size);
        }

        public void BeginWrite(byte[] buffer, int offset, int size, AsyncCallback asyncCallback)
        {
            var stream = client.GetStream();
            //writeState = state;
            writeCallback = asyncCallback;
            stream.BeginWrite(buffer, offset, size, AsyncWriteCallback, stream);
        }

        public void BeginRead(byte[] buffer, int offset, int size, AsyncCallback asyncCallback)
        {
            var stream = client.GetStream();
            //readState = state;
            readCallback = asyncCallback;

            mReadBuffer = buffer;
            mReadOffset= offset;
            mReadSize = size;

            stream.BeginRead(buffer, offset, size, AsyncReadCallback, stream);
        }

        private void AsyncWriteCallback(IAsyncResult ar)
        {
            var stream = (NetworkStream)ar.AsyncState;
            stream.EndWrite(ar);
            //ar.AsyncState = writeState;
            writeCallback(ar);
        }

        private void AsyncReadCallback(IAsyncResult ar)
        {
            var stream = (NetworkStream)ar.AsyncState;
            int readSize = stream.EndRead(ar);

            if (readSize < mReadSize)
            {
                mReadOffset += readSize;
                mReadSize -= readSize;
                stream.BeginRead(mReadBuffer, mReadOffset, mReadSize, AsyncReadCallback, stream);
            }
            else
            {
                //ar.AsyncState = readState;
                readCallback(ar);
            }
        }
    }
}
